// Copyright (c) 2023, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

@OnPlatform({'mac-os': Timeout.factor(2), 'windows': Timeout.factor(10)})
library;

import 'package:code_assets/code_assets.dart';
import 'package:collection/collection.dart';
import 'package:hooks/hooks.dart';
import 'package:native_toolchain_c/src/cbuilder/compiler_resolver.dart';
import 'package:native_toolchain_c/src/native_toolchain/apple_clang.dart';
import 'package:native_toolchain_c/src/native_toolchain/clang.dart';
import 'package:native_toolchain_c/src/native_toolchain/msvc.dart' as msvc;
import 'package:native_toolchain_c/src/tool/tool_error.dart';
import 'package:test/test.dart';

import '../helpers.dart';

void main() {
  test('Input provided compiler', () async {
    final tempUri = await tempDirForTest();
    final tempUri2 = await tempDirForTest();
    final ar =
        [
          ...await appleAr.defaultResolver!.resolve(logger: logger),
          ...await msvc.lib.defaultResolver!.resolve(logger: logger),
          ...await llvmAr.defaultResolver!.resolve(logger: logger),
        ].first.uri;
    final cc =
        [
          ...await appleClang.defaultResolver!.resolve(logger: logger),
          ...await msvc.cl.defaultResolver!.resolve(logger: logger),
          ...await clang.defaultResolver!.resolve(logger: logger),
        ].first.uri;
    final ld =
        [
          ...await appleLd.defaultResolver!.resolve(logger: logger),
          ...await msvc.msvcLink.defaultResolver!.resolve(logger: logger),
          ...await lld.defaultResolver!.resolve(logger: logger),
        ].first.uri;
    final envScript =
        [
          ...await msvc.vcvars64.defaultResolver!.resolve(logger: logger),
        ].firstOrNull?.uri;

    final targetOS = OS.current;
    final buildInputBuilder =
        BuildInputBuilder()
          ..setupShared(
            packageName: 'dummy',
            packageRoot: tempUri,
            outputFile: tempUri.resolve('output.json'),
            outputDirectoryShared: tempUri2,
          )
          ..config.setupBuild(linkingEnabled: false)
          ..addExtension(
            CodeAssetExtension(
              targetOS: targetOS,
              macOS:
                  targetOS == OS.macOS
                      ? MacOSCodeConfig(targetVersion: defaultMacOSVersion)
                      : null,
              targetArchitecture: Architecture.current,
              linkModePreference: LinkModePreference.dynamic,
              cCompiler: CCompilerConfig(
                archiver: ar,
                compiler: cc,
                linker: ld,
                windows:
                    targetOS == OS.windows
                        ? WindowsCCompilerConfig(
                          developerCommandPrompt: DeveloperCommandPrompt(
                            script: envScript!,
                            arguments: [],
                          ),
                        )
                        : null,
              ),
            ),
          );
    final buildInput = buildInputBuilder.build();
    final resolver = CompilerResolver(
      codeConfig: buildInput.config.code,
      logger: logger,
    );
    final compiler = await resolver.resolveCompiler();
    final archiver = await resolver.resolveArchiver();
    expect(compiler.uri, buildInput.config.code.cCompiler?.compiler);
    expect(archiver.uri, buildInput.config.code.cCompiler?.archiver);
    final environment = await resolver.resolveEnvironment(compiler);
    if (targetOS == OS.windows) {
      expect(environment, isNot(equals({})));
    } else {
      expect(environment, equals({}));
    }
  });

  test('No compiler found', () async {
    final tempUri = await tempDirForTest();
    final tempUri2 = await tempDirForTest();
    final buildInputBuilder =
        BuildInputBuilder()
          ..setupShared(
            packageName: 'dummy',
            packageRoot: tempUri,
            outputFile: tempUri.resolve('output.json'),
            outputDirectoryShared: tempUri2,
          )
          ..config.setupBuild(linkingEnabled: false)
          ..addExtension(
            CodeAssetExtension(
              targetOS: OS.windows,
              targetArchitecture: Architecture.arm64,
              linkModePreference: LinkModePreference.dynamic,
              cCompiler: cCompiler,
            ),
          );

    final buildInput = buildInputBuilder.build();

    final resolver = CompilerResolver(
      codeConfig: buildInput.config.code,
      logger: logger,
      hostOS: OS.android, // This is never a host.
      hostArchitecture: Architecture.arm64, // This is never a host.
    );
    expect(resolver.resolveCompiler, throwsA(isA<ToolError>()));
    expect(resolver.resolveArchiver, throwsA(isA<ToolError>()));
  });
}
